home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************
- * targa.c
- *
- * This module contains the code to read and write the Targa output file
- * format.
- *
- * from Persistence of Vision(tm) Ray Tracer
- * Copyright 1996 Persistence of Vision Team
- *---------------------------------------------------------------------------
- * NOTICE: This source code file is provided so that users may experiment
- * with enhancements to POV-Ray and to port the software to platforms other
- * than those supported by the POV-Ray Team. There are strict rules under
- * which you are permitted to use this file. The rules are in the file
- * named POVLEGAL.DOC which should be distributed with this file. If
- * POVLEGAL.DOC is not available or for more info please contact the POV-Ray
- * Team Coordinator by leaving a message in CompuServe's Graphics Developer's
- * Forum. The latest version of POV-Ray may be found there as well.
- *
- * This program is based on the popular DKB raytracer version 2.12.
- * DKBTrace was originally written by David K. Buck.
- * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
- *
- *****************************************************************************/
-
- /****************************************************************************
- *
- * Explanation:
- *
- * -
- *
- * ---
- *
- * May 1994 : Support for 24-bit RLE Targa output files added: John Baily
- * and David Payne.
- *
- * Jul 1994 : Resume trace support and minor algorithm fix (one more still
- * needed, see comments in Write_Targa_Line); resume will force
- * Targa format to match the original trace format -- the T or C
- * format flag is adjusted as necessary: Charles Marslett,
- *
- * Jun 1995 : Added support for 32-bit Targa input and output files.
- * The alpha channel has a value of 0 for 100% transparency
- * and a value of 255 for 0% transparency. [DB]
- *
- *****************************************************************************/
-
- #include "frame.h"
- #include "povproto.h"
- #include "povray.h"
- #include "targa.h"
-
-
-
- /*****************************************************************************
- * Local preprocessor defines
- ******************************************************************************/
-
- #define boolean int
-
-
-
- /*****************************************************************************
- * Local typedefs
- ******************************************************************************/
-
- typedef struct pix
- {
- DBL blue, green, red, transm;
- } pix;
-
-
-
- /*****************************************************************************
- * Local variables
- ******************************************************************************/
-
- static int Targa_Line_Number;
- static unsigned char idbuf[256];
-
-
-
- /*****************************************************************************
- * Static functions
- ******************************************************************************/
-
- static void convert_targa_color PARAMS((IMAGE_COLOUR *, unsigned, unsigned char *));
- static int Open_Targa_File PARAMS((FILE_HANDLE *handle, char *name, int *width,
- int *height, int buffer_size, int mode));
- static void Write_Targa_Line PARAMS((FILE_HANDLE *handle, COLOUR *line_data, int line_number));
- static int Read_Targa_Line PARAMS((FILE_HANDLE *handle, COLOUR *line_data, int *line_number));
- static void Close_Targa_File PARAMS((FILE_HANDLE *handle));
- static void Write_Targa_Pixel PARAMS((FILE_HANDLE *handle, DBL b, DBL g, DBL r, DBL f));
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Get_Targa_File_Handle
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- FILE_HANDLE *Get_Targa_File_Handle()
- {
- FILE_HANDLE *handle;
-
- handle = (FILE_HANDLE *)POV_MALLOC(sizeof(FILE_HANDLE), "TGA file handle");
-
- handle->Open_File_p = Open_Targa_File;
- handle->Write_Line_p = Write_Targa_Line;
- handle->Read_Line_p = Read_Targa_Line;
- handle->Read_Image_p = Read_Targa_Image;
- handle->Close_File_p = Close_Targa_File;
-
- handle->file = NULL;
- handle->buffer = NULL;
- handle->buffer_size = 0;
-
- return(handle);
- }
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Open_Targa_File
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * Jun 1995 : Added code for 32 bit Targa files. [DB]
- *
- * Sept 1995: Modified header output for Targa files. [AED]
- *
- ******************************************************************************/
-
- static int Open_Targa_File (handle, name, width, height, buffer_size, mode)
- FILE_HANDLE *handle;
- char *name;
- int *width;
- int *height;
- int buffer_size;
- int mode;
- {
- unsigned char tgaheader[18];
-
- handle->mode = mode;
- handle->filename = name;
-
- Targa_Line_Number = 0;
-
- switch (mode)
- {
- case READ_MODE:
-
- if ((handle->file = fopen(name, READ_FILE_STRING)) == NULL)
- {
- return(0);
- }
-
- if (buffer_size != 0)
- {
- handle->buffer = POV_MALLOC((size_t)buffer_size, "TGA file buffer");
- setvbuf (handle->file, handle->buffer, _IOFBF, buffer_size);
- }
-
- /* Read targa header information. */
-
- if (fread(tgaheader, 18, 1, handle->file) != 1)
- {
- return(0);
- }
-
- /* Decipher the header information */
-
- switch (tgaheader[2])
- {
- case 2 : opts.OutputFormat = 'T'; break;
- case 10 : opts.OutputFormat = 'C'; break;
- default : return(0);
- }
-
- switch (tgaheader[16])
- {
- case 24 : break;
- case 32 : opts.Options |= OUTPUT_ALPHA; break;
- default : return(0);
- }
-
- /* First_Column set to x offset. Bytes 8, 9 */
- opts.First_Column = tgaheader[8] + (tgaheader[9] << 8);
-
- /* First line set to y offset. Bytes 10, 11 */
- opts.First_Line = Targa_Line_Number = tgaheader[10] + (tgaheader[11]<<8);
-
- handle->width = *width = tgaheader[12] + (tgaheader[13] << 8);
- handle->height = *height = tgaheader[14] + (tgaheader[15] << 8);
-
- handle->buffer_size = buffer_size;
-
- break;
-
- case WRITE_MODE:
-
- if (!strcmp(name,"-"))
- {
- buffer_size = 0;
- handle->file = stdout;
- }
- else if ((handle->file = fopen (name, WRITE_FILE_STRING)) == NULL)
- {
- return(0);
- }
-
- if (buffer_size != 0)
- {
- handle->buffer = POV_MALLOC((size_t)buffer_size, "TGA file buffer");
- setvbuf (handle->file, handle->buffer, _IOFBF, buffer_size);
- }
-
- /* Output TGA file header info */
- putc(0, handle->file); /* Byte 0 - Length of Image ID field */
-
- putc(0, handle->file); /* Byte 1 - Color map type (0 is no color map) */
-
- switch(opts.OutputFormat) /* Byte 2 - TGA file type */
- {
- case 't': /* Uncompressed True-Color Image */
- case 'T': putc(2, handle->file); break;
-
- case 'c': /* Run-length compressed True-Color Image */
- case 'C': putc(10, handle->file); break;
- }
-
- putc(0, handle->file); /* Byte 3 - Index of first color map entry LSB */
- putc(0, handle->file); /* Byte 4 - Index of first color map entry MSB */
-
- putc(0, handle->file); /* Byte 5 - Color map length LSB */
- putc(0, handle->file); /* Byte 6 - Color map legth MSB */
-
- putc(0, handle->file); /* Byte 7 - Color map size */
-
- /* x origin set to "First_Column" Bytes 8, 9 */
-
- putc(opts.First_Column % 256, handle->file);
- putc(opts.First_Column / 256, handle->file);
-
- /* y origin set to "First_Line" Bytes 10, 11 */
-
- putc(opts.First_Line % 256, handle->file);
- putc(opts.First_Line / 256, handle->file);
-
- /* write width and height Bytes 12 - 15 */
-
- putc(*width % 256, handle->file);
- putc(*width / 256, handle->file);
- putc(*height % 256, handle->file);
- putc(*height / 256, handle->file);
-
- /* We write 24 or 32 bits/pixel (16 million colors and alpha channel)
- * and also store the orientation and Alpha channel depth. Bytes 16, 17.
- */
- if (opts.Options & OUTPUT_ALPHA)
- {
- putc(32, handle->file); /* 32 bits/pixel (BGRA) */
- putc(0x28, handle->file); /* Data starts at top left, 8 bits Alpha */
- }
- else
- {
- putc(24, handle->file); /* 24 bits/pixel (BGR) */
- putc(0x20, handle->file); /* Data starts at top left, 0 bits Alpha */
- }
-
- /* TGA file Image ID field data would go here (up to 255 chars) */
-
- handle->width = *width;
- handle->height = *height;
-
- handle->buffer_size = buffer_size;
-
- break;
-
- case APPEND_MODE:
-
- if (!strcmp(name,"-"))
- {
- buffer_size = 0;
- handle->file = stdout;
- }
- else if ((handle->file = fopen (name, APPEND_FILE_STRING)) == NULL)
- {
- return(0);
- }
-
- if (buffer_size != 0)
- {
- handle->buffer = POV_MALLOC((size_t)buffer_size, "TGA file buffer");
- setvbuf (handle->file, handle->buffer, _IOFBF, buffer_size);
- }
-
- break;
- }
-
- return(1);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Write_Targa_Pixel
- *
- * INPUT
- *
- * handle - Current file handel
- * r, g, b, f - Color values to write
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * Dan Farmer
- *
- * DESCRIPTION :
- *
- * Moves redundant code to a single function. Adding 16 bit grayscale
- * conditional code to each occurance of writing a pixel was getting a bit
- * too wordy.
- *
- * CHANGES
- *
- * Jun 1995 : Added code for 32 bit Targa files. [DB]
- *
- * Sept 1995: Modified handling of Alpha channel to use only opts.Options
- * Sept 1995: Modified handling of grayscale to use only opts.Options
- *
- ******************************************************************************/
-
- static void Write_Targa_Pixel (handle, b, g, r, f)
- FILE_HANDLE *handle;
- DBL r, g, b, f;
- {
- unsigned int gray;
-
- if (opts.Options & HF_GRAY_16)
- {
- /* Ouput heightfield in POV red/green format */
- gray = ((0.30 * r) + (0.59 * g) + (0.11 * b)) * 65535;
-
- if ((putc(0 , handle->file) == EOF) ||
- (putc(gray & 0xFF, handle->file) == EOF) ||
- (putc((gray >> 8) & 0xFF, handle->file) == EOF))
- {
- Error("Error writing TGA output data to %s.\n",handle->filename);
- }
- }
- else
- {
- /* Normal 24/32 bit pixel coloring */
-
- if ((putc((int) floor(b * 255.0), handle->file) == EOF) ||
- (putc((int) floor(g * 255.0), handle->file) == EOF) ||
- (putc((int) floor(r * 255.0), handle->file) == EOF))
- {
- Error("Error writing TGA output data to %s.\n",handle->filename);
- }
-
- if (opts.Options & OUTPUT_ALPHA)
- {
- if (putc((int) floor((1.0 - f) * 255.0), handle->file) == EOF)
- {
- Error("Error writing TGA output data to %s.\n",handle->filename);
- }
- }
- }
- }
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Write_Targa_Line
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * Jun 1995 : Added code for 32 bit Targa files. [DB]
- *
- ******************************************************************************/
-
- static void Write_Targa_Line (handle, line_data, line_number)
- FILE_HANDLE *handle;
- COLOUR *line_data;
- int line_number;
- {
- register int x;
- int ptype, cnt, llen, startx;
- boolean writenow;
- pix curpix, nexpix;
-
- switch (opts.OutputFormat)
- {
- case 't':
- case 'T':
-
- for (x = 0; x < handle->width; x++)
- {
- Write_Targa_Pixel (handle, line_data[x][BLUE], line_data[x][GREEN], line_data[x][RED], line_data[x][TRANSM]);
- }
-
- break;
-
- case 'c':
- case 'C':
-
- llen = handle->width;
-
- startx = 0;
-
- cnt = 1;
-
- curpix.blue = line_data[startx][BLUE];
- curpix.green = line_data[startx][GREEN];
- curpix.red = line_data[startx][RED];
- curpix.transm = line_data[startx][TRANSM];
-
- ptype = 0;
-
- writenow = FALSE;
-
- for (;;)
- {
- nexpix.blue = line_data[startx+cnt][BLUE];
- nexpix.green = line_data[startx+cnt][GREEN];
- nexpix.red = line_data[startx+cnt][RED];
- nexpix.transm = line_data[startx+cnt][TRANSM];
-
- if ((nexpix.red == curpix.red) && (nexpix.blue == curpix.blue) &&
- (nexpix.green == curpix.green) && (nexpix.transm == curpix.transm))
- {
- if (ptype == 0)
- {
- cnt++;
-
- if ((cnt >= 128) || ((startx + cnt) >= llen))
- {
- writenow = TRUE;
- }
- }
- else
- {
- cnt--;
-
- writenow = TRUE;
- }
- }
- else
- {
- if ((ptype == 1) || (cnt <= 1))
- {
- ptype = 1;
-
- curpix = nexpix;
-
- cnt++;
-
- if ((cnt >= 128) || ((startx + cnt) >= llen))
- {
- writenow = TRUE;
- }
- }
- else
- {
- writenow = TRUE;
- }
- }
-
- if (writenow)
- {
- /* This test SHOULD be unnecessary! However, it isn't! [CWM] */
-
- if (startx + cnt > llen)
- {
- cnt = llen - startx;
- }
-
- if (ptype == 0)
- {
- putc((int) ((cnt - 1) | 0x80), handle->file);
-
- Write_Targa_Pixel (handle, curpix.blue, curpix.green, curpix.red, curpix.transm);
-
- curpix = nexpix;
- }
- else
- {
- putc((int) cnt - 1, handle->file);
-
- for (x = 0; x < cnt; x++)
- {
- Write_Targa_Pixel (handle,
- line_data[startx+x][BLUE], line_data[startx+x][GREEN],
- line_data[startx+x][RED], line_data[startx+x][TRANSM]);
- }
- }
- startx = startx + cnt;
-
- writenow = FALSE;
-
- ptype = 0;
-
- cnt = 1;
-
- if (startx >= llen)
- {
- break; /* Exit while */
- }
- }
- }
-
- break; /* End of case */
- }
-
- if (handle->buffer_size == 0)
- {
- /* Close and reopen file (if not stdout) for integrity in case we crash */
-
- fflush(handle->file);
-
- if (strcmp(handle->filename, "-"))
- {
- handle->file = freopen(handle->filename, APPEND_FILE_STRING, handle->file);
- }
- }
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Read_Targa_Line
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * Jun 1995 : Added code for 32 bit Targa files. [DB]
- *
- ******************************************************************************/
-
- static int Read_Targa_Line (handle, line_data, line_number)
- FILE_HANDLE *handle;
- COLOUR *line_data;
- int *line_number;
- {
- int x, data, cnt;
- DBL rdata, gdata, bdata, fdata;
-
- switch (opts.OutputFormat)
- {
- case 't':
- case 'T':
-
- for (x = 0; x < handle->width; x++)
- {
- /* Read the BLUE data byte. If EOF is reached on the first
- * character read, then this line hasn't been rendered yet.
- * Return 0. If an EOF occurs somewhere within the line, this
- * is an error - return -1.
- */
-
- if ((data = getc(handle->file)) == EOF)
- {
- if (x == 0)
- {
- return(0);
- }
- else
- {
- return(-1);
- }
- }
-
- line_data[x][BLUE] = (DBL) data / 255.0;
-
- /* Read the GREEN data byte. */
-
- if ((data = getc(handle->file)) == EOF)
- {
- return(-1);
- }
-
- line_data[x][GREEN] = (DBL) data / 255.0;
-
- /* Read the RED data byte. */
-
- if ((data = getc(handle->file)) == EOF)
- {
- return(-1);
- }
-
- line_data[x][RED] = (DBL) data / 255.0;
-
- /* Read alpha channel. */
-
- if (opts.Options & OUTPUT_ALPHA)
- {
- if ((data = getc(handle->file)) == EOF)
- {
- return(-1);
- }
-
- line_data[x][TRANSM] = 1.0 - (DBL)data / 255.0;
- }
- else
- {
- line_data[x][TRANSM] = 0.0;
- }
- }
-
- break;
-
- case 'c':
- case 'C':
-
- cnt = 0;
-
- do
- {
- if ((data = getc(handle->file)) == EOF)
- {
- if (cnt == 0)
- {
- return(0);
- }
- else
- {
- return(-1);
- }
- }
-
- if (data & 0x80)
- {
- x = data & 0x7F;
-
- if ((data = getc(handle->file)) == EOF)
- {
- return(-1);
- }
-
- bdata = (DBL) data / 255.0;
-
- if ((data = getc(handle->file)) == EOF)
- {
- return(-1);
- }
-
- gdata = (DBL) data / 255.0;
-
- if ((data = getc(handle->file)) == EOF)
- {
- return(-1);
- }
-
- rdata = (DBL) data / 255.0;
-
- /* Read alpha channel if any. */
-
- if (opts.Options & OUTPUT_ALPHA)
- {
- if ((data = getc(handle->file)) == EOF)
- {
- return(-1);
- }
-
- fdata = 1.0 - (DBL)data / 255.0;
- }
- else
- {
- fdata = 0.0;
- }
-
- do
- {
- line_data[cnt][BLUE] = bdata;
- line_data[cnt][GREEN] = gdata;
- line_data[cnt][RED] = rdata;
- line_data[cnt][TRANSM] = fdata;
-
- cnt++;
- }
- while (--x != -1);
- }
- else
- {
- x = data & 0x7F;
-
- do
- {
- if ((data = getc(handle->file)) == EOF)
- {
- return(-1);
- }
-
- bdata = (DBL) data / 255.0;
-
- if ((data = getc(handle->file)) == EOF)
- {
- return(-1);
- }
-
- gdata = (DBL) data / 255.0;
-
- if ((data = getc(handle->file)) == EOF)
- {
- return(-1);
- }
-
- rdata = (DBL) data / 255.0;
-
- /* Read alpha channel if any. */
-
- if (opts.Options & OUTPUT_ALPHA)
- {
- if ((data = getc(handle->file)) == EOF)
- {
- return(-1);
- }
-
- fdata = 1.0 - (DBL)data / 255.0;
- }
- else
- {
- fdata = 0.0;
- }
-
- line_data[cnt][BLUE] = bdata;
- line_data[cnt][GREEN] = gdata;
- line_data[cnt][RED] = rdata;
- line_data[cnt][TRANSM] = fdata;
-
- cnt++;
- }
- while (--x != -1);
- }
- }
- while (cnt < handle->width);
-
- if (cnt != handle->width)
- {
- return(-1);
- }
-
- break;
- }
-
- *line_number = Targa_Line_Number++;
-
- return(1);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Close_Targa_File
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- static void Close_Targa_File (handle)
- FILE_HANDLE *handle;
- {
- if (handle->file)
- {
- fflush(handle->file);
- fclose (handle->file);
- }
-
- if (handle->buffer != NULL)
- {
- POV_FREE (handle->buffer);
- }
-
- handle->file = NULL;
- handle->buffer = NULL;
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * convert_targa_color
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- static void convert_targa_color(tcolor, pixelsize, bytes)
- IMAGE_COLOUR *tcolor;
- unsigned pixelsize;
- unsigned char *bytes;
- {
- switch (pixelsize)
- {
- case 1:
-
- tcolor->Red = bytes[0];
- tcolor->Green = bytes[0];
- tcolor->Blue = bytes[0];
- tcolor->Filter = 0;
- tcolor->Transmit = 0;
-
- break;
-
- case 2:
-
- tcolor->Red = ((bytes[1] & 0x7c) << 1);
- tcolor->Green = (((bytes[1] & 0x03) << 3) | ((bytes[0] & 0xe0) >> 5)) << 3;
- tcolor->Blue = (bytes[0] & 0x1f) << 3;
- tcolor->Filter = 0;
- tcolor->Transmit = 255 - (bytes[1] & 0x80 ? 255 : 0);
-
- break;
-
- case 3:
-
- tcolor->Red = bytes[2];
- tcolor->Green = bytes[1];
- tcolor->Blue = bytes[0];
- tcolor->Filter = 0;
- tcolor->Transmit = 0;
-
- break;
-
- case 4:
-
- tcolor->Red = bytes[2];
- tcolor->Green = bytes[1];
- tcolor->Blue = bytes[0];
- tcolor->Filter = 0;
- tcolor->Transmit = 255 - bytes[3];
-
- break;
-
- default:
-
- Error("Bad pixelsize in TGA color.\n");
- }
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Read_Targa_Image
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * Reads a Targa image into an RGB image buffer. Handles 8, 16, 24, 32 bit
- * formats. Raw or color mapped. Simple raster and RLE compressed pixel
- * encoding. Right side up or upside down orientations.
- *
- * CHANGES
- *
- * Jun 1995 : Added code for 32 bit Targa files. [DB]
- *
- ******************************************************************************/
-
- void Read_Targa_Image(Image, name)
- IMAGE *Image;
- char *name;
- {
- int h;
- int temp;
- unsigned i, j, k;
- /* unsigned long i, j, k; */
- unsigned char cflag = 0, *map_line = NULL, bytes[4], tgaheader[18];
- unsigned ftype, idlen, cmlen, cmsiz, psize, orien;
- unsigned width, height;
- FILE *filep;
- IMAGE_LINE *line_data = NULL;
- IMAGE_COLOUR *cmap, pixel;
-
- /* Start by trying to open the file */
-
- if ((filep = Locate_File(name, READ_FILE_STRING,".tga",".TGA",TRUE)) == NULL)
- {
- Error ("Error opening TGA image.\n");
- }
-
- if (fread(tgaheader, 18, 1, filep) != 1)
- {
- Error ("Error reading header of TGA image.\n");
- }
-
- /* Decipher the header information */
-
- idlen = tgaheader[ 0];
- ftype = tgaheader[ 2];
- cmlen = tgaheader[ 5] + (tgaheader[ 6] << 8);
- cmsiz = tgaheader[ 7] / 8;
- width = tgaheader[12] + (tgaheader[13] << 8);
- height = tgaheader[14] + (tgaheader[15] << 8);
- psize = tgaheader[16] / 8;
- orien = tgaheader[17] & 0x20; /* Right side up ? */
-
- Image->iwidth = width;
- Image->iheight = height;
- Image->width = (DBL)width;
- Image->height = (DBL)height;
- Image->Colour_Map_Size = cmlen;
- Image->Colour_Map = NULL;
-
- /* Determine if this is a supported Targa type */
-
- if (ftype == 9 || ftype == 10 || ftype == 11)
- {
- cflag = 1;
- }
- else
- {
- if (ftype == 1 || ftype == 2 || ftype == 3)
- {
- cflag = 0;
- }
- else
- {
- Error("Unsupported file type %d in TGA image.\n", ftype);
- }
- }
-
- /* Skip over the picture ID information */
-
- if (idlen > 0 && fread(idbuf, idlen, 1, filep) != 1)
- {
- Error ("Error reading header from TGA image.\n");
- }
-
- /* Read in the the color map (if any) */
-
- if (cmlen > 0)
- {
- if (psize != 1)
- {
- Error("Unsupported color map bit depth (%d bpp) in TGA image.\n",
- psize * 8);
- }
-
- cmap = (IMAGE_COLOUR *)POV_MALLOC(cmlen * sizeof(IMAGE_COLOUR), "TGA color map");
-
- for (i = 0; i < cmlen; i++)
- {
- for (j = 0; j < cmsiz; j++)
- {
- if ((temp = fgetc(filep)) == EOF)
- {
- Error("Error reading color map from TGA image.\n");
- }
- else
- {
- bytes[j] = (unsigned char)temp;
- }
- }
-
- convert_targa_color(&cmap[i], cmsiz, bytes);
- }
-
- Image->Colour_Map = cmap;
- }
- else
- {
- Image->Colour_Map = NULL;
- }
-
- /* Allocate the buffer for the image */
-
- if (cmlen > 0)
- {
- Image->data.map_lines = (unsigned char **)POV_MALLOC(height * sizeof(unsigned char *), "TGA image");
- }
- else
- {
- Image->data.rgb_lines = (IMAGE_LINE *)POV_MALLOC(height * sizeof(IMAGE_LINE), "TGA image");
- }
-
- for (i = 0; i < height; i++)
- {
- k = width * sizeof(unsigned char);
-
- if (cmlen > 0)
- {
- map_line = (unsigned char *)POV_MALLOC((size_t)k, "TGA image line");
-
- Image->data.map_lines[i] = map_line;
- }
- else
- {
- line_data = &Image->data.rgb_lines[i];
-
- line_data->red = (unsigned char *)POV_MALLOC((size_t)k, "TGA image line");
- line_data->green = (unsigned char *)POV_MALLOC((size_t)k, "TGA image line");
- line_data->blue = (unsigned char *)POV_MALLOC((size_t)k, "TGA image line");
-
- if (psize > 3)
- {
- line_data->transm = (unsigned char *)POV_MALLOC((size_t)k, "TGA image line");
- }
- else
- {
- line_data->transm = (unsigned char *)NULL;
- }
- }
- }
-
- /* Read the image into the buffer */
-
- if (cflag)
- {
- /* RLE compressed images */
-
- if (cmlen > 0)
- {
- if (orien)
- {
- map_line = Image->data.map_lines[0];
- }
- else
- {
- map_line = Image->data.map_lines[height-1];
- }
- }
- else
- {
- if (orien)
- {
- line_data = &Image->data.rgb_lines[0];
- }
- else
- {
- line_data = &Image->data.rgb_lines[height-1];
- }
- }
-
- i = 0; /* row counter */
- j = 0; /* column counter */
-
- while (i < height)
- {
- /* Grab a header */
-
- if ((h = fgetc(filep)) == EOF)
- {
- Error("Error reading data from TGA image.\n");
- }
-
- if (h & 0x80)
- {
- /* Repeat buffer */
-
- h &= 0x7F;
-
- for (k = 0; k < psize; k++)
- {
- if ((temp = fgetc(filep)) == EOF)
- {
- Error("Error reading data from TGA image.\n");
- }
- else
- {
- bytes[k] = (unsigned char)temp;
- }
- }
-
- if (cmlen == 0)
- {
- convert_targa_color(&pixel, psize, bytes);
- }
-
- for (; h >= 0; h--)
- {
- if (cmlen > 0)
- {
- map_line[j] = bytes[0];
- }
- else
- {
- line_data->red[j] = (unsigned char)pixel.Red;
- line_data->green[j] = (unsigned char)pixel.Green;
- line_data->blue[j] = (unsigned char)pixel.Blue;
- if (psize > 3)
- {
- line_data->transm[j] = (unsigned char)pixel.Transmit;
- }
- }
-
- if (++j == width)
- {
- i++;
-
- if (cmlen > 0)
- {
- if (orien)
- {
- map_line = Image->data.map_lines[i];
- }
- else
- {
- map_line = Image->data.map_lines[height-i-1];
- }
- }
- else
- {
- line_data += (orien ? 1 : -1);
- }
-
- j = 0;
- }
- }
- }
- else
- {
- /* Copy buffer */
-
- for (; h >= 0; h--)
- {
- for (k = 0; k < psize ; k++)
- {
- if ((temp = fgetc(filep)) == EOF)
- {
- Error("Error reading data from TGA image.\n");
- }
- else
- {
- bytes[k] = (unsigned char)temp;
- }
- }
-
- if (cmlen > 0)
- {
- map_line[j] = bytes[0];
- }
- else
- {
- convert_targa_color(&pixel, psize, bytes);
-
- line_data->red[j] = (unsigned char)pixel.Red;
- line_data->green[j] = (unsigned char)pixel.Green;
- line_data->blue[j] = (unsigned char)pixel.Blue;
- if (psize > 3)
- {
- line_data->transm[j] = (unsigned char)pixel.Transmit;
- }
- }
-
- if (++j == width)
- {
- i++;
-
- if (cmlen > 0)
- {
- if (orien)
- {
- map_line = Image->data.map_lines[i];
- }
- else
- {
- map_line = Image->data.map_lines[height-i-1];
- }
- }
- else
- {
- line_data += (orien ? 1 : -1);
- }
-
- j = 0;
- }
- }
- }
- }
- }
- else
- {
- /* Simple raster image file, read in all of the pixels */
-
- if (cmlen == 0)
- {
- if (orien)
- {
- line_data = &Image->data.rgb_lines[0];
- }
- else
- {
- line_data = &Image->data.rgb_lines[height-1];
- }
- }
-
- for (i = 0; i < height; i++)
- {
- if (cmlen > 0)
- {
- if (orien)
- {
- map_line = Image->data.map_lines[i];
- }
- else
- {
- map_line = Image->data.map_lines[height-i-1];
- }
- }
-
- for (j = 0; j < width; j++)
- {
- for (k = 0; k < psize; k++)
- {
- if ((temp = fgetc(filep)) == EOF)
- {
- Error("Error reading data from TGA image.\n");
- }
- else
- {
- bytes[k] = (unsigned char)temp;
- }
- }
-
- if (cmlen > 0)
- {
- map_line[j] = bytes[0];
- }
- else
- {
- convert_targa_color(&pixel, psize, bytes);
-
- line_data->red[j] = (unsigned char)pixel.Red;
- line_data->green[j] = (unsigned char)pixel.Green;
- line_data->blue[j] = (unsigned char)pixel.Blue;
- if (psize > 3)
- {
- line_data->transm[j] = (unsigned char)pixel.Transmit;
- }
- }
- }
-
- if (cmlen == 0)
- {
- line_data += (orien ? 1 : -1);
- }
- }
- }
-
- /* Any data following the image is ignored. */
-
- /* Close the image file */
-
- fclose(filep);
- }
-